package server;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.LinkedList;

import javax.management.timer.Timer;

/*
 * enthaelt nur main-Methode
 * */
public class EchoServer {

	/*
	 * stellt Verbindung von Client zu Server und erstellt pro Client einen neuen Thread
	 * */
	public static void main(String[] args) throws Exception {
		ServerSocket m_ServerSocket = new ServerSocket(1238);
		int id = 0;
		while (true) {
			Socket clientSocket = m_ServerSocket.accept();
			ClientServiceThread cliThread = new ClientServiceThread(
					clientSocket, id++);
			cliThread.start();
		}
	}
}

/*
 * speichert Namen aller Spieler und verwaltet Text, ermittelt Gewinner
 * */
class ClientServiceThread extends Thread {
	Socket clientSocket;
	int clientID = -1;
	boolean running = true;
	static volatile LinkedList<String> text;
	static volatile String[] benutzer;
	int saveId = 0;
	static volatile boolean serverVohanden;
	boolean isServer = false;
	static volatile String sendeText;
	static volatile boolean gewonnen = false;
	static volatile String gewonnerSpieler;

	static void wait(int a) throws InterruptedException {
		sleep(a);
	}

	/*
	 * erzeugt aus dem Text in help ein Spielfeld gr^2
	 * und gibt es als zeilenweise zusammengefuegten String zurueck
	 * */

	public String getSpielfeld(int gr, LinkedList<String> help)
	throws IOException {
		String f = "";
		String[] helps = new String[gr * gr];
		String[] b = new String[help.size()];
		//konvertieren des Textes in help zu einem String []
		help.toArray(b);
		boolean voranden = false;
		int i = 0;
		while (i < gr * gr) {
			//waehle zufaelig ein Wort aus dem [] b aus
			String x = b[(int) Math.floor((Math.random() * b.length))];
			//pruefen, dass das Wort nicht schon im Spielfeld liegt
			for (int j = 0; j < helps.length; j++) {
				if (x.equals(helps[j])) {
					voranden = true;
				}
			}
			if (!voranden) {
				helps[i++] = x;
			}
			voranden = false;
		}
		//zusammenfuegen des String [] zu einem String, zeilenweise
		for (int j = 0; j < helps.length; j++) {
			f = f + helps[j] + " ";
		}
		return f;
	}

	/*
	 * speichern des Sockets und der Client-ID in Member-Variablen
	 * */
	ClientServiceThread(Socket s, int i) {
		clientSocket = s;
		clientID = i;
		if (benutzer == null) {
			benutzer = new String[100];
		}

	}

	/*
	 * entfernt Punkte, Kommata etc. aus dem Text und gibt eine Liste aus kleingeschriebenen Worten zurueck
	 * */
	public LinkedList<String> getText(String text) {
		String[] a;
		LinkedList<String> b = new LinkedList<String>();
		text = text.toLowerCase();
		text = text.replaceAll(",", "");
		text = text.replaceAll("\\.", "");
		System.out.println(text);
		//trennen des Textes in Worte
		a = text.split(" ", 0);
		for (int i = 0; i < a.length; i++) {
			b.add(a[i]);
		}
		return b;
	}

	/*
	 * 
	 * */
	public void run() {
		System.out
		.println("Accepted Client : ID - " + clientID + " : Address - "
				+ clientSocket.getInetAddress().getHostName());
		try {
			//oeffnen on Reader und Writer fuer den Server
			BufferedReader in = new BufferedReader(new InputStreamReader(
					clientSocket.getInputStream()));
			PrintWriter out = new PrintWriter(new OutputStreamWriter(
					clientSocket.getOutputStream()));

			// ---------------------------------------------------------
			//eingabe des Spielernamens, verweigert Eingabe identischer Spielernamen
			String name;
			name = in.readLine();
			int i = 0;
			Boolean nameVorhanden = false;
			for (int j = 0; j < benutzer.length; j++) {
				if (name.equals(benutzer[j])) {
					nameVorhanden = true;
				}
			}
			if (!nameVorhanden) {
				out.println("yes");
				out.flush();
				while (i < benutzer.length) {
					if (benutzer[i] == null) {
						this.saveId = i;
						benutzer[i] = new String(name);
						i = benutzer.length;

					}
					i++;
				}

				String ServOrClient;
				ServOrClient = in.readLine();
				boolean gefunden = false;
				//wenn es noch keinen Server gibt, muss das der Server sein
				if (ServOrClient.equals("Server") && !this.serverVohanden) {
					this.serverVohanden = true;
					out.println("Server");
					out.flush();
					String a = in.readLine();
					//einlesen des Textes zum Spielen vom Client
					this.text = getText(a);
					isServer = true;
					gefunden = true;

				}

				if (this.serverVohanden && gefunden == false) {
					out.println("Client");
					out.flush();
				}
				//erstelle ein Spielfeld der Goesse 5
				String a = getSpielfeld(5, this.text);
				out.println(a);
				out.flush();

				String sendUser = "";
				while (running) {
					//wenn das der Server ist, schick das naechste Wort an die Clients
					if (isServer) {
						this.sendeText = this.text.pop();
					}
					if (!serverVohanden) {
						out.println("quit quit");
						out.flush();
					}
					if (gewonnen) {
						out.println("win " + gewonnerSpieler);
						out.flush();
						out.println("quit quit");
						out.flush();
						break;
					}
					sendUser = "user ";
					wait(3000);
					out.println("word " + this.sendeText);
					out.flush();
					try {
						//anhalten, wenn Client etwas anderes als ping antwortet
						if (!in.readLine().equals("ping")) {
							running = false;
							break;
						}
					} catch (Exception e) {
						running = false;
					}
					try {
						//pruefen, ob einer der Clients einen Sieg gemeldet hat und ggf Gewinner melden
						if (in.readLine().equals("win")) {
							gewonnerSpieler = benutzer[this.saveId];
							out.println("win " + benutzer[this.saveId]);
							out.flush();
							this.gewonnen = true;
						}
					} catch (Exception e) {

					}

					try {
						if (!in.readLine().equals("ping")) {
							running = false;
							break;
						}
					} catch (Exception e) {
						running = false;
					}

					for (int j = 0; j < benutzer.length; j++) {
						if (benutzer[j] != null) {
							sendUser = sendUser + benutzer[j] + ",";
						}

					}
					//Ausgabe aller Benutzer
					out.println(sendUser);
					out.flush();
				}
				benutzer[this.saveId] = null;
				//falls der Name schon vorhanden ist
			} else {
				out.println("no");
				out.flush();
			}
			//wenn Server und Schleife zu Ende, Server abmelden
			if (isServer) {
				serverVohanden = false;
				gewonnen = false;
				System.out.println("Server Raus");
			}
			clientSocket.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
